library ieee;
use ieee.std_logic_1164.all;

entity controllerBlock is
	port (
		reset, start, setMuliplicand, setMultiplier, overFlow, clk: in bit;
		clr, regmulti, enCtr, shift, done : out bit;
		holdShift, enLoad : out bit
	);
end entity controllerBlock;

architecture DATAFLOW of ControllerBlock is

	component dFlipFlop is
	port (
		d, clk, clr_al : in bit;
		q, qn : out bit
	);
	end component; 
	
	for all : dFlipFlop use entity work.dFlipFlop(DATAFLOW);

	signal dVec : bit_vector(5 downTo 0);
	signal dVecNot : bit_vector(5 downTo 0);
	signal dVecIn : bit_vector(5 downTo 0);
	signal shenigans : bit;
	signal clrIn: bit := '1';
	signal notOverFlow : bit := not overFlow;
	
begin
  
  	dVecIn(0) <= reset or (dVec(0) and not start);
  	dVecIn(1) <= not reset and ((dVec(0) and start) or (not setMuliplicand and dVec(1)));
  	dVecIn(2) <= not reset and ((dVec(1) and setMuliplicand) or (setMultiplier and dVec(2)));
  	dVecIn(3) <= ((not reset and not overFlow) and (dVec(4) or (dVec(2) and not setMultiplier)));
  	dVecIn(4) <= ((not reset and not overFlow) and dVec(3));
  	dVecIn(5) <= not reset and ((overFlow and (dVec(5) or dVec(4) or dVec(3))) or dVec(5));
  	
	
	--clrIn appears to be an active low signal in dFlipFlop	
	dFlipFlop0 : dFlipFlop  port map(dVecIn(0), clk, clrIn, dVec(0), dVecNot(0));
	dFlipFlop1 : dFlipFlop  port map(dVecIn(1), clk, clrIn, dVec(1), dVecNot(1));
	dFlipFlop2 : dFlipFlop  port map(dVecIn(2), clk, clrIn, dVec(2), dVecNot(2));
	dFlipFlop3 : dFlipFlop  port map(dVecIn(3), clk, clrIn, dVec(3), dVecNot(3));
	dFlipFlop4 : dFlipFlop  port map(dVecIn(4), clk, clrIn, dVec(4), dVecNot(4));
	dFlipFlop5 : dFlipFlop  port map(dVecIn(5), clk, clrIn, dVec(5), dVecNot(5));
	
	dFlipFlopShenigans : dFlipFlop  port map(dVec(2), clk, clrIn, shenigans);
	
	clr <= dVec(0);
	regMulti <= dVec(1) or dVec(2) or shenigans;
	enCtr <= dVec(3);
	shift <= dVec(4);
	done <= dVec(5);
	enLoad <= dVec(1) or dVec(3) or dVec(4);
	
end architecture DATAFLOW;

architecture STRUCTURAL of controllerBlock is
	
	component dFlipFlop is
	port (
		d, clk, clr_al : in bit;
		q, qn : out bit
	);
	end component; 
	
	component and2
	
	port(a,b : in bit;
		z : out bit
	);
	
	end component; 
	
	component or2
	
	port(a,b : in bit;
		z : out bit
	);
	
	end component;
	
		
	for all : dFlipFlop use entity work.dFlipFlop(DATAFLOW);

	
	signal andVec : bit_vector(12 downTo 0);
	signal orVec : bit_vector(7 downTo 0);
	signal dVec : bit_vector(5 downTo 0);
	signal dVecNot : bit_vector(5 downTo 0);
	signal clrIn: bit := '1';
	signal out0 : bit;
	signal notStart : bit := not start;
	signal notSetMuliplicand : bit := not setMuliplicand;
	signal notSetMultiplier : bit := not setMultiplier;
	signal notReset : bit := not reset;
	signal notOverFlow : bit := not overFlow;
	
	
begin
	
	AND_0 : and2  port map(notStart, dVec(0), andVec(0));
	AND_1 : and2  port map(dvec(0), start, andVec(1));
	AND_2 : and2  port map(notSetMuliplicand, dVec(1), andVec(2));
	AND_3 : and2  port map(dVec(1), setMuliplicand, andVec(3));
	AND_4 : and2  port map(notSetMultiplier, dVec(2), andVec(4));
	AND_5 : and2  port map(dVec(2), setMultiplier, andVec(5));
	AND_6 : and2  port map(notReset, notOverFlow, andVec(6));
	AND_7 : and2  port map(dVec(3), andVec(6), andVec(7));
	AND_8 : and2  port map(notReset, overFlow, andVec(8));
	
	OR_0 : or2 port map(andVec(0), reset, orVec(0)); 
	OR_1 : or2 port map(andVec(1), andVec(2), orVec(1)); 
	OR_2 : or2 port map(andVec(3), andVec(4), orVec(2)); 
	OR_3 : or2 port map(dVec(4), andVec(5), orVec(3)); 
	OR_4 : or2 port map(dVec(4), dVec(3), orVec(4)); 
	OR_5 : or2 port map(orVec(4), dVec(5), orVec(5));
	
	AND_9 : and2  port map(notReset, orVec(1), andVec(9));
	AND_10 : and2  port map(notReset, orVec(2), andVec(10));
	AND_11 : and2  port map(orVec(3), andVec(6), andVec(11));	
	AND_12 : and2  port map(orVec(5), andVec(8), andVec(12));
	
	OR_6 : or2 port map(andVec(12), dVec(5), orVec(6));   
	
	--clrIn appears to be an active low signal in dFlipFlop	
	dFlipFlop0 : dFlipFlop  port map(orVec(0), clk, clrIn, dVec(0), dVecNot(0));
	dFlipFlop1 : dFlipFlop  port map(andVec(9), clk, clrIn, dVec(1), dVecNot(1));
	dFlipFlop2 : dFlipFlop  port map(andVec(10), clk, clrIn, dVec(2), dVecNot(2));
	dFlipFlop3 : dFlipFlop  port map(andVec(11), clk, clrIn, dVec(3), dVecNot(3));
	dFlipFlop4 : dFlipFlop  port map(andVec(7), clk, clrIn, dVec(4), dVecNot(4));
	dFlipFlop5 : dFlipFlop  port map(orVec(06), clk, clrIn, dVec(5), dVecNot(5));
	
	OR_7 : or2 port map(dVec(3), dVec(4), out0);	
	
	clr <= dVec(0);
	regMulti <= dVec(1);
	enCtr <= out0;
	shift <= dVec(4);
	done <= dVec(5);


end STRUCTURAL;